package org.vectrics.recruiter.struts.admin.employee;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import javax.servlet.jsp.JspException;

import org.apache.commons.lang.StringUtils;
import org.vectrics.common.util.DateSync;
import org.vectrics.common.util.DateUtil;
import org.vectrics.employee.Employee;
import org.vectrics.location.Location;
import org.vectrics.provider.CoreServiceLocator;
import org.vectrics.recruiter.RecruitServiceLocator;
import org.vectrics.recruiter.job.JobFunction;
import org.vectrics.recruiter.job.JobTerm;
import org.vectrics.recruiter.struts.employee.EmployeeForm;
import org.vectrics.struts.Request;
import org.vectrics.struts.VectricsActionData;
import org.vectrics.struts.VectricsStrutsAction;

import com.hexacta.hrs.domain.employee.history.AgreementCondition;
import com.hexacta.hrs.domain.employee.history.AssignabilityStatus;
import com.hexacta.hrs.domain.employee.history.CareerRole;
import com.hexacta.hrs.domain.employee.history.MentorAssignment;
import com.hexacta.hrs.domain.staffing.assignment.EmployeeAssignment;

/**
 * @author pgoette
 * 
 */
public class SaveEmployeeAction extends VectricsStrutsAction {

    private static final String ADD = "ADD";

    // private EmployeeAssignmentService employeeAssignmentService;

    /**
     * 
     * 
     * @see org.vectrics.struts.VectricsStrutsAction#doExecute(org.vectrics.struts
     *      .VectricsActionData)
     */
    @Override
    protected String doExecute(final VectricsActionData actionData) throws JspException {
        // Obtengo la request
        Request request = actionData.getRequest();
        // Busco el formulario
        EmployeeForm employeeForm = (EmployeeForm) actionData.getForm();

        // Busco el empleado con el id de empleado
        Employee employee = RecruitServiceLocator.getCompanyService().findEmployee(new Long(employeeForm.getId()));

        // Seteo el id de usuario como atributo a la request para que la tome la
        // pagina de view del usuario.
        request.setAttribute("userId", employee.getPerson().getId().toString());
        // Si presiono cancelar salgo y no se realiza la validaci�n.
        if (actionData.wasButtonPressed("cancel"))
            return "cancel";

        saveOrUpdate(actionData, employeeForm, employee);

        return "success";
    }

    private void saveOrUpdate(final VectricsActionData actionData, final EmployeeForm employeeForm,
            final Employee employee) {

        CareerRole careerRole = null;
        MentorAssignment mentorAssignment = null;
        AgreementCondition agreementCondition = null;
        AssignabilityStatus assignabilityStatus = null;

        Date dateStart = DateUtil.getFecha(employeeForm.getDateStart());
        Date recordEffectiveDay = DateUtil.getFecha(employeeForm.getRecordEffectiveDay());

        boolean changeCareerRole = false;
        boolean changeAgreementCondition = false;
        boolean changeMentor = false;
        boolean changeAssignability = false;

        careerRole = employee.createEmploymentConditionHistoryIfIsNull().getCareerRole(recordEffectiveDay);
        mentorAssignment = employee.createEmploymentConditionHistoryIfIsNull().getMentorAssignment(recordEffectiveDay);
        agreementCondition = employee.createEmploymentConditionHistoryIfIsNull().getAgreementCondition(
                recordEffectiveDay);
        assignabilityStatus = employee.createEmploymentConditionHistoryIfIsNull().getAssignabilityStatus(
                recordEffectiveDay);

        if (careerRole == null) {
            careerRole = new CareerRole();
            changeCareerRole = employee.getEmploymentConditionHistory().getCareerRoles().isEmpty();
        } else {
            changeCareerRole = !careerRole.getEffectiveDate().equals(recordEffectiveDay);
        }

        if (mentorAssignment == null) {
            mentorAssignment = new MentorAssignment();
            changeMentor = employee.getEmploymentConditionHistory().getMentorAssignments().isEmpty();
        } else {
            changeMentor = !mentorAssignment.getEffectiveDate().equals(recordEffectiveDay);
        }

        if (agreementCondition == null) {
            agreementCondition = new AgreementCondition();
            changeAgreementCondition = employee.getEmploymentConditionHistory().getAgreementConditions().isEmpty();
        } else {
            changeAgreementCondition = !new Long(agreementCondition.getEffectiveDate().getTime())
                    .equals(recordEffectiveDay.getTime());
        }

        boolean assignable = employeeForm.isElegibleProjectMember();
        if (assignabilityStatus == null) {
            assignabilityStatus = new AssignabilityStatus();
            changeAssignability = employee.getEmploymentConditionHistory().getAssignabilityStatuses().isEmpty();
        } else {
            changeAssignability = !assignabilityStatus.getEffectiveDate().equals(recordEffectiveDay)
                    && assignable != assignabilityStatus.isAvailable();
        }

        employee.setDateStart(dateStart);

        // Cambios en Career Role

        // Si function no es nulo o vacio
        JobFunction function = employee.getFunction();
        if (!StringUtils.isEmpty(employeeForm.getFunction())) {
            // Busco la fuction
            function = RecruitServiceLocator.getJobProvider().findFunction(employeeForm.getFunction());

            changeCareerRole = changeCareerRole || !function.equals(employee.getFunction());
        }

        changeCareerRole = changeCareerRole
                || !employee.getCareerRolePosition().equals(new Long(employeeForm.getCareerRolePosition()));

        // Recupero el jobTerm
        JobTerm jobTerm = RecruitServiceLocator.getJobProvider().findJobTermForCode(employeeForm.getStatus());
        // Si es igual
        if (employee.getCurrentStatus() != null
                && employee.getCurrentStatus().getStatusType().getId().equals(jobTerm.getId())) {
            if (!StringUtils.isEmpty(employeeForm.getDate())) {
                employee.getCurrentStatus().setDateStart(DateUtil.getFecha(employeeForm.getDate()));
            } else {
                employee.getCurrentStatus().setDateStart(DateUtil.getFecha(employeeForm.getDateStart()));
            }
        } else {
            changeCareerRole = true;
        }

        // Cambios en Agreement Condition

        // Si la location es distinta de null la seteo al empleado.
        Location location = null;
        if (!StringUtils.isEmpty(employeeForm.getLocation())) {
            location = RecruitServiceLocator.getLocationService().findLocation(new Long(employeeForm.getLocation()));
            changeAgreementCondition = changeAgreementCondition || !employee.getLocation().equals(location);
        } else {
            location = employee.getLocation();
        }

        Double hoursPerDay = new Double(employeeForm.getHoursPerDay());

        changeAgreementCondition = changeAgreementCondition || !hoursPerDay.equals(employee.getHoursPerDay());

        String medicalInsurance = null;
        if (employeeForm.getMedicalInsurance() != null) {
            changeAgreementCondition = changeAgreementCondition || employee.getMedicalInsurance() == null
                    || employee.getMedicalInsurance() != null
                    && !employee.getMedicalInsurance().equals(employeeForm.getMedicalInsurance());
            medicalInsurance = employeeForm.getMedicalInsurance();
        } else {
            medicalInsurance = employee.getMedicalInsurance();
        }

        // Cambios en mentor

        Employee mentor = null;
        if (!StringUtils.isEmpty(employeeForm.getIdMentor())) {
            mentor = (Employee) CoreServiceLocator.getCompanyService().findEmployeeForIdPerson(
                    new Long(employeeForm.getIdMentor()));
            if (changeMentor || !employee.getMentor().equals(mentor)) {
                mentorAssignment.setMentor(mentor);
                mentorAssignment.setEffectiveDate(recordEffectiveDay);
                employee.createEmploymentConditionHistoryIfIsNull().getMentorAssignments().add(mentorAssignment);
            }
        }

        if (employeeForm.getLastAgreementDay() != null) {
            employee.setLastAgreementDay(DateUtil.getFecha(employeeForm.getLastAgreementDay()));
        }

        employee.setElegibleMentor(employeeForm.isElegibleMentor());

        employee.setLastModifiedBy(actionData.getAuthPerson());
        employee.setLastModifiedDate(DateSync.getCurrentTime());

        changeAssignability = changeAssignability
                || assignable != employee.getEmploymentConditionHistory().getAssignable(recordEffectiveDay);
        if (changeAssignability) {
            saveAssignabilityStatus(assignable, employee, recordEffectiveDay, assignabilityStatus);
        }

        if (changeCareerRole) {
            saveCareerRole(employeeForm, function, employee, recordEffectiveDay, jobTerm, careerRole);
        }

        if (changeAgreementCondition) {
            saveAgreementCondition(employee, recordEffectiveDay, location, hoursPerDay, medicalInsurance,
                    agreementCondition);
        }

        employee.update(DateUtil.getFecha(employeeForm.getDate()));

        CoreServiceLocator.getCompanyService().updateCompanyPerson(employee);

        if (employee.getDateEnd() != null) {

            Date end = employee.getDateEnd();
            List<EmployeeAssignment> assignments = CoreServiceLocator.getEmployeeAssignmentService()
                    .findAssignmentsByEmployee(employee);

            for (EmployeeAssignment eas : assignments) {

                if (eas.getStartDate().getTime().after(end)) {
                    Calendar newStart = new GregorianCalendar();
                    newStart.setTime(end);
                    eas.setStartDate(newStart);
                }

                if (eas.getEndDate().getTime().after(end)) {
                    Calendar newEnd = new GregorianCalendar();
                    newEnd.setTime(end);
                    eas.setEndDate(newEnd);
                }

                CoreServiceLocator.getEmployeeAssignmentService().save(eas);

            }
        }

    }

    /**
     * @param assignable
     * @param employee
     * @param recordEffectiveDay
     * @param assignabilityStatus
     */
    private void saveAssignabilityStatus(final boolean assignable, final Employee employee,
            final Date recordEffectiveDay, final AssignabilityStatus assignabilityStatus) {
        assignabilityStatus.setAvailable(assignable);
        assignabilityStatus.setEffectiveDate(recordEffectiveDay);
        employee.createEmploymentConditionHistoryIfIsNull().addAssignabilityStatus(assignabilityStatus);
    }

    private void saveAgreementCondition(final Employee employee, final Date dateStart, final Location location,
            final Double hoursPerDay, final String medicalInsurance, final AgreementCondition agreementCondition) {
        agreementCondition.setEffectiveDate(dateStart);
        agreementCondition.setHoursPerDay(hoursPerDay);
        agreementCondition.setLocation(location);
        agreementCondition.setMedicalInsurance(medicalInsurance);
        employee.createEmploymentConditionHistoryIfIsNull().getAgreementConditions().add(agreementCondition);
    }

    private void saveCareerRole(final EmployeeForm employeeForm, final JobFunction function, final Employee employee,
            final Date dateStart, final JobTerm jobTerm, final CareerRole careerRole) {
        careerRole.setCareerRole(function);
        careerRole.setCareerRolePosition(new Long(employeeForm.getCareerRolePosition()));
        careerRole.setCondition(jobTerm);
        careerRole.setEffectiveDate(dateStart);
        employee.createEmploymentConditionHistoryIfIsNull().getCareerRoles().add(careerRole);
    }

    // /**
    // * @return the employeeAssignmentService
    // */
    // public EmployeeAssignmentService getEmployeeAssignmentService() {
    // return employeeAssignmentService;
    // }
    //
    // /**
    // * @param employeeAssignmentService
    // * the employeeAssignmentService to set
    // */
    // public void setEmployeeAssignmentService(final EmployeeAssignmentService
    // employeeAssignmentService) {
    // this.employeeAssignmentService = employeeAssignmentService;
    // }

}
